#pragma once

#include <map>
#include <memory>

#include "api/p2pms_client_interface.hpp"
#include "base_call_agent.hpp"
#include "ws_msg_dispatcher.hpp"
#include "api/peer_connection_interface.h"
#include "nlohmann/json.hpp"
#include "sfu_client.hpp"

// libmediasoupclient
#include "Device.hpp"
#include "Transport.hpp"
#include "api/p2pms_common.hpp"

namespace p2pms
{

//==================================================================================================
// 
//==================================================================================================
class P2SPCallAgent : public BaseCallAgent, public ISFUClientHandler
{
public:
	P2SPCallAgent(
		CallRole role,
		const std::string& user_id,
		IPcFactoryPtr factory,
		ICallHandler* handler,
		rtc::Thread* thread,
		std::shared_ptr<IMsgDispatcher> dispatcher);
	~P2SPCallAgent();

	// ICallAgent implementation
	ErrCode Init() override;
	ErrCode MakeCall(const std::string& callee_id) override;
	ErrCode IncomingCall(const CallMakeNotifyData& notify_data) override;
	void TerminateCall() override;
	ErrCode StartPublish(const MediaInfo& media) override;
	ErrCode StopPublish(const MediaInfo& media) override;
	ErrCode StartSubscribe(const std::string& user_id, const MediaInfo& media) override;
	ErrCode StopSubscribe(const std::string& user_id, const MediaInfo& media) override;
	void OnTimer() override;

	// ISFUClientHandler
	void OnJoinRoomResult(bool result) override;
	void OnStartPublishResult(
		const MediaInfo& media,
		bool result) override;
	void OnStopPublishResult(
		const MediaInfo&
		media, bool result) override;
	void OnStartPublishNotify(
		const std::string& user_id,
		const MediaInfo& media) override;
	void OnStopPublishNotify(
		const std::string& user_id,
		const MediaInfo& media) override;
	void OnStartSubscribeResult(
		const std::string& user_id,
		const MediaInfo& media,
		bool ressult) override;
	void OnStopSubscribeResult(
		const std::string& user_id,
		const MediaInfo& media,
		bool ressult) override;
	void OnAddTrack(
		const std::string& user_id,
		const MediaInfo& media,
		webrtc::MediaStreamTrackInterface* track) override;
	void OnRemoveTrack(
		const std::string& user_id,
		const MediaInfo& media,
		webrtc::MediaStreamTrackInterface* track) override;

private:
	void CallStateChanged(CallState state);
	void ClearUp();
	bool ParseCallMakeRes(const Message& msg, CallMakeResData& data);
	void OnCallMakeRes(const Message& msg, CBType cbt);
	void OnCallEndNotify(const Message& msg, CBType cbt);
	bool DoTerminateCall();

private:	
	ICallHandler* m_call_handler = nullptr;
	rtc::Thread* m_sdk_thread = nullptr;
	std::shared_ptr<IMsgDispatcher> m_dispatcher;
	SFUClient m_sfu_client;
};

}